fix: keep conda and virtualenv activation across session restore - #2367
fix: keep conda and virtualenv activation across session restore#2367happysnehal111-del wants to merge 1 commit into
Conversation
📝 WalkthroughWalkthroughThe change detects Conda and venv activations across platforms. Pane snapshots store activation metadata. Workspace capture, terminal restoration, and deferred agent resume preserve this state and apply its environment variables to launches. ChangesVirtual environment persistence
Estimated code review effort: 4 (Complex) | ~45 minutes Merge Risk: 🟡 Moderate · up to The PR changes session restoration to preserve Conda and virtualenv environments, but the current head can still restore an idle pane or live-handoff shell with the wrong interpreter, and the supplied evidence retains a Windows test assertion failure. Persisted environment prefixes also affect executable lookup without ownership validation. The PR needs fixes or explicit owner acceptance before merge. Sequence Diagram(s)sequenceDiagram
participant Tab
participant TerminalRuntime
participant PaneRuntime
participant PlatformProcessReader
participant Snapshot
participant Restore
participant Terminal
Tab->>TerminalRuntime: request foreground_virtual_env
TerminalRuntime->>PaneRuntime: request foreground_virtual_env
PaneRuntime->>PlatformProcessReader: read process environment
PlatformProcessReader-->>PaneRuntime: return VirtualEnvActivation
PaneRuntime-->>TerminalRuntime: return activation
TerminalRuntime-->>Tab: return activation
Tab->>Snapshot: capture activation
Snapshot-->>Restore: provide saved activation
Restore->>Terminal: apply activation during launch
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 5
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 19bca225-41b0-4f49-8c9d-8d125c9b9874
📒 Files selected for processing (12)
src/app/agent_resume.rssrc/pane.rssrc/persist/restore.rssrc/persist/snapshot.rssrc/platform/fallback.rssrc/platform/linux.rssrc/platform/macos.rssrc/platform/mod.rssrc/platform/windows.rssrc/terminal/runtime.rssrc/terminal/state.rssrc/workspace/tab.rs
7d17ab3 to
e6308ed
Compare
|
Note GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer. |
Greptile SummaryThe PR persists conda and virtualenv activation metadata with pane snapshots and reapplies it when restoring panes or resuming agents.
Confidence Score: 5/5The PR appears safe to merge because no blocking failure remains within the eligible follow-up-review scope. No blocking failure remains.
|
| Filename | Overview |
|---|---|
| src/platform/mod.rs | Defines activation metadata, parsing, and cross-platform launch-environment reconstruction. |
| src/persist/snapshot.rs | Adds optional virtual-environment snapshot capture while retaining additive-format compatibility. |
| src/persist/restore.rs | Validates saved prefixes and carries restored activation into terminal launch and deferred resume state. |
| src/pane.rs | Applies activation variables during pane launch and exposes foreground activation detection. |
| src/app/agent_resume.rs | Reuses the terminal’s restored activation when spawning a resumed agent. |
| src/platform/linux.rs | Reads activation from procfs with process-state and WSL safeguards. |
| src/platform/macos.rs | Reads activation from the macOS process argument and environment block. |
| src/platform/windows.rs | Reads and parses activation variables from the target process environment. |
Sequence Diagram
sequenceDiagram
participant P as Foreground process
participant S as Snapshot capture
participant D as Session snapshot
participant R as Session restore
participant T as Restored terminal
P->>S: Read activation environment
S->>D: Store kind, prefix, and name
D->>R: Load optional virtual_env
R->>R: Validate prefix and rebuild PATH
R->>T: Launch with activation variables
Reviews (3): Last reviewed commit: "fix: keep conda and virtualenv activatio..." | Re-trigger Greptile
ogulcancelik
left a comment
There was a problem hiding this comment.
this needs another pass before merge:
process_virtual_env()unconditionally reads/proc/<pid>/environduring snapshot capture. that reintroduces the exact remote-memory-backed WSL stall guarded by #2179. please rebase after #2179 and apply the same state/WSL safety policy to this read.launch_env(std::env::var("PATH"))rebuilds from the server process PATH. for deferred resume this can overwrite the effective pane-launch PATH, including the local-attach refresh in #2854. derive from the effective launch environment after that work is reconciled instead.- add Windows unit coverage for
virtual_env_from_utf16and Windows conda/venv path construction; this path is currently only compile-checked. - because snapshot capture now adds a synchronous process-environment read per pane on the main loop, report 1-pane versus 15-pane save-capture scaling before merge.
please also add the user-facing changelog entry and rerun checks and both review bots on the rebased head.
e6308ed to
69dd516
Compare
|
Note GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer. |
There was a problem hiding this comment.
Actionable comments posted: 1
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 53bbeae9-2933-4b77-97b9-7f6cfdc80170
📒 Files selected for processing (13)
docs/next/CHANGELOG.mdsrc/app/agent_resume.rssrc/pane.rssrc/persist/restore.rssrc/persist/snapshot.rssrc/platform/fallback.rssrc/platform/linux.rssrc/platform/macos.rssrc/platform/mod.rssrc/platform/windows.rssrc/terminal/runtime.rssrc/terminal/state.rssrc/workspace/tab.rs
🚧 Files skipped from review as they are similar to previous changes (10)
- src/terminal/runtime.rs
- src/persist/restore.rs
- src/workspace/tab.rs
- src/platform/windows.rs
- src/platform/macos.rs
- src/platform/mod.rs
- src/platform/fallback.rs
- src/terminal/state.rs
- src/app/agent_resume.rs
- src/persist/snapshot.rs
Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review.
| #[test] | ||
| fn pane_launch_env_builds_the_activation_path_on_the_effective_launch_path() { | ||
| // Anything that sets PATH ahead of the activation has to survive it, | ||
| // so the activation is composed against the value the pane would have | ||
| // launched with rather than against the server's own PATH. | ||
| let mut cmd = CommandBuilder::new("shell"); | ||
| let launch_env = | ||
| PaneLaunchEnv::from_extra(vec![("PATH".to_string(), "/refreshed/bin".to_string())]) | ||
| .with_virtual_env(Some(crate::platform::VirtualEnvActivation { | ||
| kind: crate::platform::VirtualEnvKind::Conda, | ||
| prefix: "/opt/conda/envs/web".into(), | ||
| name: Some("web".to_string()), | ||
| })); | ||
|
|
||
| apply_pane_launch_env(&mut cmd, &launch_env); | ||
|
|
||
| let path = cmd.get_env("PATH").expect("expected PATH"); | ||
| assert_eq!( | ||
| std::env::split_paths(path).collect::<Vec<_>>(), | ||
| [ | ||
| std::path::PathBuf::from("/opt/conda/envs/web/bin"), | ||
| std::path::PathBuf::from("/refreshed/bin"), | ||
| ] | ||
| ); | ||
| assert_eq!( | ||
| cmd.get_env("CONDA_PREFIX"), | ||
| Some(std::ffi::OsStr::new("/opt/conda/envs/web")) | ||
| ); | ||
| } |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Gate this Unix-specific test.
On Windows, Conda activation adds the prefix and five Windows-specific directories. This assertion expects only <prefix>/bin and /refreshed/bin. Windows test runs will fail.
Add #[cfg(not(windows))] to this test, or add a Windows-specific expected path list.
As per coding guidelines: “Rust platform-specific code must be compile-gated.”
Source: Coding guidelines
A pane working inside an activated conda environment or virtualenv came back from restore on the shell's default environment, so an agent resumed into that pane ran against the wrong interpreter. Panes now record the activation prefix alongside their cwd, and restore hands it back to the shell it spawns, including the deferred spawn that resumes an agent. PATH is rebuilt from the prefix instead of replayed from the snapshot so a restored pane follows the current machine, and an environment that has been removed since the save is dropped rather than re-entered. The restored shell re-runs the user's rc files, so conda's automatic base activation is suppressed for it; otherwise base lands on PATH ahead of whatever was restored. The activation is carried on PaneLaunchEnv rather than expanded into launch variables at the call site, so its PATH is built from the PATH the pane actually launches with instead of the server's own. Reading a foreground process environment on Linux now goes through the same state and WSL guards as the other remote-memory-backed proc reads.
69dd516 to
a27b82d
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: dd7ef60e-fd86-431a-9d2a-b3ca6ba3cb4e
📒 Files selected for processing (1)
src/pane.rs
Included review availability: Your plan provides up to 10 included reviews per hour; 8 remain after this review.
| let foreground = crate::platform::foreground_process_group_id(pid)?; | ||
| // An idle prompt leaves the shell itself in the foreground, and the | ||
| // shell's own activation is the part that cannot be read. | ||
| if foreground == pid { | ||
| return None; |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift
Preserve activation at an idle shell prompt.
Line 3059 returns None when the shell is foreground. After a user activates Conda or a venv and returns to the prompt, normal session capture takes this branch. src/workspace/tab.rs:598 then receives no activation, so the restored pane loses the environment.
Record an activation state that remains available at the prompt, such as through shell integration, instead of treating an idle shell as having no activation.
Problem
A pane that was working inside an activated conda environment or virtualenv comes back from a session restore on the shell's default environment. The agent resumes, but against the wrong interpreter —
python,pip, and anything else installed into the environment resolve outside it.Restore spawns the pane's shell with an empty
PaneLaunchEnv, and the snapshot has nowhere to record an activation, so there is nothing to hand back.How the environment is read
A shell mutates its own environment in place when it activates one, and that mutation is not visible from outside the process. What is visible is the environment a process was launched with, so the pane's foreground process group leader — the command the shell started — carries the activation that was in effect when it began. In the case that matters, that process is the agent.
The primitives for this were already here:
/proc/<pid>/environon Linux,KERN_PROCARGS2on macOS, and the PEB read on Windows. This adds one function per platform on top of them, and a fallback stub elsewhere.What gets stored
Only the activation prefix and its display name, not a copy of
PATH.PATHis rebuilt from the prefix on restore, so a restored pane follows the current machine rather than being pinned to whatever it looked like when the snapshot was written. Entries already on the inheritedPATHare not repeated, so repeated restores cannot grow it.PaneSnapshot.virtual_envis optional and skipped when absent, soSNAPSHOT_VERSIONstays at 3 and sessions written by this build still load on older ones.conda's automatic base activation
Restored panes come back as interactive login shells, so they re-run the user's rc files, and conda's init hook activates
baseby default. That runs after the environment is handed in and replaces it. It shadows a restored virtualenv too, becausebaselands ahead of it onPATH.CONDA_AUTO_ACTIVATEandCONDA_AUTO_ACTIVATE_BASEare therefore set tofalsefor restored panes that have a recorded environment — both spellings, since conda renamed the setting in 25.x. Panes without a recorded environment are untouched and still auto-activatebaseas before.Testing
cargo fmt --check,cargo clippy --all-targets -- -D warnings, and the cross-target Windows clippy fromjust windows-lintare clean.cargo nextest runpasses except for three tests that fail identically on an unmodifiedmasteron this machine:live_handoff_keeps_agent_started_pane_after_agent_exits,live_handoff_keeps_unmanaged_agent_name_bound_to_saved_session, andpane_info_and_subscriptions_expose_done_agent_status.venvcome back with the right prefix and withpythonresolving into the environment.